#include <iostream>
#include <string>
#include <memory>
#include "TcpServer.hpp"
#include "Protocol.hpp"
#include "cal.hpp"
using namespace socket_ns;
using namespace protocol_ns;

using service_t = std::function<Response(Request)>;

class IOService
{
public:
    IOService(service_t service)
        : _service(service)
    {
    }
    void Service(socket_sptr socket, INetAddr addr)
    {
        std::string clientAddr = "[" + addr.IP() + ":" + std::to_string(addr.Port()) + "] ";
        LOG(INFO, "get a link from %s\n", clientAddr.c_str());

        std::string inbuffer;
        while (true)
        {
            // 1. 接收序列化数据
            int n = socket->Recv(inbuffer);
            if(n <= 0)
            {
                LOG(INFO, "%s is quit\n", clientAddr);
                break;
            }

            // 2. 是否是完整的报文
            std::string message;
            while ((message = DeCode(inbuffer)) != "")
            {
                std::cout << "recv request 序列化 : " << message << std::endl;
                // 数据不是完整的，继续读取
                // if (message == "")
                //     continue;
                // 3.读取到完整的序列化的数据，进行反序列化得到数据
                Request req;
                req.DeSerialize(message);


                // 4. 对数据进行操作得到结果
                //  调用处理函数
                // Response res = _func(req);
                Response res = _service(req);

                // 5.序列化response
                std::string send_message;
                res.Serialize(send_message);
                std::cout << "send response 序列化 : " << send_message << std::endl;

                // 6.为序列化数据添加报头
                send_message = EnCode(send_message);
                std::cout << "send response 报文 : " << send_message;

                // 7.发送数据给client
                socket->Send(send_message);
            }
        }
    }
    ~IOService()
    {
    }

private:
    service_t _service;
};

void Useage(const std::string &s)
{
    std::cout << "Useage" << ":\n\t" << s << " port\n";
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Useage(argv[0]);
        exit(0);
    }
    uint16_t port = std::stoi(argv[1]);
    // 应用层
    Cal cal;
    // 表示层
    IOService ioser(std::bind(&Cal::Excute, &cal, std::placeholders::_1));

    io_service_t service = std::bind(&IOService::Service, &ioser, std::placeholders::_1, std::placeholders::_2);
    // 会话层
    std::unique_ptr<TcpServer> usvr = std::make_unique<TcpServer>(port, service);
    usvr->Loop();

    return 0;
}
